#ifndef DRV_SOFT_I2C_H__
#define DRV_SOFT_I2C_H__

#include "ct_i2c.h"
#include "ct_type.h"

#define SLAVE_ADDRESS    0xEB
#define ML51_I2C_ADDRESS 0xA4
#define READ_DATA_ERROR  0xFF

// Special status macros
#define CT_ERR_I2C_EXIT_MS_MODE 0xF8    // Exit master/slave mode

#define CT_SOFT_I2C_MODE_OUT_PP 0
#define CT_SOFT_I2C_MODE_OUT_OD 1
#define CT_SOFT_I2C_MODE_INPUT  2

typedef struct {
    uint8_t byte;
    uint8_t error;
} soft_i2c_single_t;

typedef struct {
    uint8_t *buffer;    // Pointer to data buffer
    uint8_t  length;    // Length of data to write
    uint8_t  error;     // Error status
} soft_i2c_buffer_t;

typedef enum { ACK = 0,
               NOT_ACK } I2C_Status_t;

/**
 * @brief Writes a byte of data to a specific address on a specific slave device.
 *        Stops and returns if an error occurs during the write process.
 * @param _slave_addr Address of the slave device.
 * @param _reg Address to write data to.
 * @param _byte Data byte to write.
 * @return uint8_t - Returns 0 if write was successful, non-zero error code otherwise.
 *
 * @details
 * ----If there are multiple slave devices,
 * an additional parameter can be added to write the address of the slave device.
 */
uint8_t ct_soft_i2c_WriteAddrByte(uint8_t _slave_addr, uint8_t _reg, uint8_t _byte);

/**
 * @brief Continuously writes data to a specific address and checks for ACK after each
 * byte.
 * @param i2c_data Struct containing buffer and length of data to write.
 * @param _slave_addr Address to write data to.
 * @param _reg Register to write data to.
 * @retval None
 */
void ct_soft_i2c_Write_8Reg(soft_i2c_buffer_t *i2c_data, uint8_t _slave_addr, uint8_t _reg);

/**
 * @brief Write data to a 16-bit register over I2C.
 *
 * @param i2c_data Pointer to a soft_i2c_buffer_t structure that contains the data to be
 * written and the length of the data.
 * @param _slave_addr The 7-bit I2C slave address of the target device.
 * @param _reg The 16-bit register address where the data will be written.
 * @retval None
 */
void ct_soft_i2c_Write_16Reg(soft_i2c_buffer_t *i2c_data, uint8_t _slave_addr, uint16_t _reg);
/**
 * @brief Reads a byte of data from a specific address with error checking.
 * @param result Pointer to a soft_i2c_t struct where the read data and error status will
 * be stored.
 * @param _slave_addr I2C slave device address.
 * @param _reg Address to read data from.
 * @return void
 */
uint8_t ct_soft_i2c_ReadAddrByte(soft_i2c_single_t *result, uint8_t _slave_addr, uint8_t _reg);
/**
 * @brief Continuously reads multiple bytes from a given I2C slave device starting from a
 * specified register.
 *
 * @param i2c_data Pointer to a `soft_i2c_t` structure that contains the buffer for
 * storing read data, the number of bytes to read, and a variable to store any error
 * status.
 * @param _slave_addr The 7-bit I2C address of the slave device.
 * @param _reg The register address from which the read operation should start.
 *
 * @note The caller must ensure that the buffer in `i2c_data` is large enough to hold the
 * number of bytes specified.
 */
void ct_soft_i2c_Read_8Reg(soft_i2c_buffer_t *i2c_data, uint8_t _slave_addr, uint8_t _reg);

/**
 * @brief Read data from a 16-bit register address over I2C.
 *
 * @param i2c_data Pointer to a soft_i2c_buffer_t structure that contains the buffer
 *                 into which the read data will be stored, along with the length of
 *                 the data to be read.
 * @param _slave_addr The 7-bit I2C slave address of the device from which to read.
 *                    The address should be right-aligned, without the read/write bit.
 * @param _reg The 16-bit register address from which to start reading.
 *
 * @note This function assumes that the lower-level I2C functions such as
 * ct_soft_i2c_Start, ct_soft_i2c_SendByte, etc., are implemented correctly and handle the
 * I2C protocol details.
 * @retval None
 */
void ct_soft_i2c_Read_16Reg(soft_i2c_buffer_t *i2c_data, uint8_t _slave_addr, uint16_t _reg);

#endif /* __SOFT_I2C_H__*/
